#include "clientxmlparser.h"

ClientXMLParser::ClientXMLParser(QObject *parent) :
    QObject(parent)
{
}

/**
* @brief XML-parser for <group> - tag
*
* creates the group in the buddymodel and adds all its buddies as well.
* @param p the QDomNode starting with the <group> tag
*/
void SslClient::parseGroup(QDomNode p)
{
    QString groupname  = p.attributes().namedItem("name").nodeValue();
    this->buddymodel->addGroup(groupname);
    p = p.firstChildElement(); // get rid of <group..>
    while (!p.isNull() && p.toElement().tagName() != "")
    {

        QDomNode name_node = p.firstChildElement("name");
        QDomNode jid_node = p.firstChildElement("jid");
        if (name_node.isNull() || jid_node.isNull())
        {
            qDebug() << "Either Name or JID not available for a buddy. Invalid XML Error";
            continue;
        }
        this->buddymodel->addBuddy(groupname,name_node.toElement().text(),jid_node.toElement().text(),1);
        p = p.nextSibling();
    }

}

/**
* @brief XML-parser for <status> - tag
* FIXME use this information gathered here
*/
void SslClient::parseStatus(QDomNode p)
{
   QDomNode jid_node    = p.firstChildElement("jid");
   QDomNode text_node   = p.firstChildElement("text");
   QDomNode type_node   = p.firstChildElement("type");
   QDomNode accid_node  = p.firstChildElement("accid");
   QDomNode res_node    = p.firstChildElement("resource");

   if (jid_node.isNull() || text_node.isNull() || type_node.isNull() || accid_node.isNull() || res_node.isNull())
   {
        qDebug() << "invalid XML error while parsing Status info";
        return;
   }
   // FIXME do something useful here
   qDebug() << jid_node.toElement().text() << text_node.toElement().text() << type_node.toElement().text();
}

/**
* @brief XML-parser: <statechanged> - tag
*
* This is chat notifications according to XEP-0085
* possible states are: none,active,inactive,composing,paused,gone
*/
void SslClient::parseState(QDomNode p)
{
    QDomNode from_node  = p.firstChildElement("jid");
    QDomNode state_node = p.firstChildElement("state");
    QDomNode accid_node = p.firstChildElement("accid");

    if(from_node.isNull() || state_node.isNull() || accid_node.isNull())
    {
        qDebug() << "incomplete state received, dropping";
        return;
    }

    int accid = accid_node.toElement().text().toInt();
    QString jid = from_node.toElement().text();

    // get the chatwidget (if exists) or create it
    // and notify about state change
    getChatWidget(
                    accid,
                    jid,
                    getBuddyName(accid,jid)
                 )->stateChanged(state_node.toElement().text());
}

/**
* @brief XML-parser:  <message> - tag
*
* parse message and deliver to the correct chatWidget
*/
void SslClient::parseMessage(QDomNode p)
{
    /**
      p points to a <message> tag
      BUT there can be multiple Siblings of <message> tags
      e.g. sending some messages in a row for backlog fetching
      We dont take this into account, yet. <- FIXME
      */
    QDomNode accid_node   = p.firstChildElement("accid");
    QDomNode to_node      = p.firstChildElement("to");
    QDomNode content_node = p.firstChildElement("content");
    QDomNode date_node    = p.firstChildElement("date");
    QDomNode from_node    = p.firstChildElement(("from"));




    if  (to_node.isNull() || from_node.isNull() || accid_node.isNull()  || content_node.isNull() || date_node.isNull())
    {
        // Either Node is not present? cant parse message then!
        // currently we drop the message while issuing a note on the debug output
        qDebug() << "Received a Message from the core with incomplete xml-information. Dropping it";
        return;
    }


    int accid = accid_node.toElement().text().toInt();
    QString my_jid = this->accData.value(accid).value("jid").toString();
    QString to  = to_node.toElement().text();
    QString from = from_node.toElement().text();
    QString foreign_jid;

    if (my_jid == to)
    {
        foreign_jid = from;
    }
    else if (my_jid == from)
    {
        foreign_jid = to;
    }
    else
    {
        qDebug() << "received an invalid message that didnt match neither from nor to. Dropping";
        qDebug() << to << from << my_jid;
        return;
    }

    // get the Chatwidget and hand over the message
    getChatWidget(
                    accid,
                    foreign_jid,
                    getBuddyName(accid,foreign_jid)
                 )->msgRecv(
                                from,
                                content_node.toElement().text(),
                                QDateTime::fromString(date_node.toElement().text(),Qt::ISODate)
                           );
}

/**
* @brief XML-parser: <buddylist> - tag
*
* When a buddylist tag is received, we freshen the BuddyModel with new data.
*/
void SslClient::parseBuddyList(QDomNode p)
{
    // clear the buddymodel
    this->buddymodel = new BuddyModel();
    this->form->buddyView->setModel(this->buddymodel);

    form->buddyView->hideColumn(2); // jid col
    form->buddyView->setColumnWidth(1,20); // Icon col
    form->buddyView->setColumnWidth(0,180); // Name col
    form->buddyView->setEditTriggers(QAbstractItemView::NoEditTriggers); // disable editing (== readOnly)

    // open Chat widget on double click
    connect(form->buddyView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(openChatWithBuddy(QModelIndex)));

    p = p.firstChildElement(); // get rid of <buddylist>

    while (!p.isNull() && p.toElement().tagName() != "")
    {
        // group definition
        if (p.toElement().tagName() == "group")
        {
            parseGroup(p);
            p = p.nextSibling();
        }
        else
        {
            qDebug() << "eror in  buddylist parsing because of "<<p.toElement().tagName();
            //break
            p = p.nextSibling();
        }

    }
    // expand all groups
    form->buddyView->expandAll();
}
